#include "VMBinaryCode.h"
#include "lang/Exception.h"
using namespace yzrilyzr_lang;
using namespace yzrilyzr_array;

namespace yzrilyzr_vmp{
	VMBinaryCode::~VMBinaryCode(){
		delete code;
	}
	VMBinaryCode::VMBinaryCode(ByteArray & file){
		check=binaryChecksum(file);
		if(!check){
			throw IOException("VMBinaryCode corrupted.");
		}
		BufferReader reader((uint8_t *)file._array, file.length);
		version=reader.readInt();
		int32_t stringConstantSize=reader.readInt();
		int32_t exportedGlobalSize=reader.readInt();
		int32_t codeLength=reader.readInt();
		this->length=codeLength;
		code=new uint8_t[codeLength];
		reader.readFully(code, codeLength);
	}
	bool VMBinaryCode::binaryChecksum(ByteArray & file){
		int32_t crc=0x00;
		int32_t poly=0x07;
		for(u_index i=0;i < file.length - 4;i++){
			int32_t byte=file[i] & 0xff;
			crc^=byte;
			for(u_index ii=0; ii < 8; ii++){
				if(crc & 0x80){
					crc=(crc << 1) ^ poly;
				} else{
					crc<<=1;
				}
			}
		}
		int32_t fileCrc=0;
		fileCrc=(fileCrc << 8) | (file[file.length - 4] & 0xff);
		fileCrc=(fileCrc << 8) | (file[file.length - 3] & 0xff);
		fileCrc=(fileCrc << 8) | (file[file.length - 2] & 0xff);
		fileCrc=(fileCrc << 8) | (file[file.length - 1] & 0xff);
		return crc == fileCrc;
	}
}